/*
 *
 * SeguridadFacade.java
 * Copyright(c) 2013 UcentralSoft, Todos los derechos reservados 
 */
package controlador;

import modelo.*;
import java.io.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import sun.misc.BASE64Encoder;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Maneja el acceso a la seguridad del sistema
 *
 * @version 1.0 [2013/10/13]
 * @author Jorge Barrera
 */
@WebServlet(name = "SeguridadFacade", urlPatterns = {"/SeguridadFacade"})
public class SeguridadFacade extends HttpServlet {

    private SeguridadDAL dataAcces;

    /**
     * Maneja las peticiones por get al servlet
     *
     * @param request
     * @param response
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        ProcessRequest(request, response);
    }

    /**
     * Maneja las peticiones por post al servlet
     *
     * @param request
     * @param response
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) {
        ProcessRequest(request, response);
    }

    /**
     * Se encarga de manejar todas las peticiones, evalÃºa el origen y devuelve
     * la información esperada
     *
     * @param request
     * @param response
     * @throws SQLException
     * @throws ClassNotFoundException
     */
    private void ProcessRequest(HttpServletRequest request, HttpServletResponse response) {
        PrintWriter out = null;
        String html = "";
        try {
            dataAcces = new SeguridadDAL();
            out = response.getWriter();
            String page = request.getParameter("page");
            if (page.equals("CargarMenu")) {
                response.setContentType("text/xml;charset=UTF-8");
                html = CargarMenu(request);
            }
            if (page.equals("UsuarioLogin")) {
                response.setContentType("text/html;ISO-8859-1");
                html = UsuarioLogin(request);
            }
            if (page.equals("UsuarioLogOut")) {
                response.setContentType("text/html;ISO-8859-1");
                html = UsuarioLogOut(request);
            }
            if (page.equals("CrearUsuario")) {
                response.setContentType("text/html;ISO-8859-1");
                html = CrearUsuario(request);
            }
            if (page.equals("ConsultarUsuarios")) {
                html = ConsultarUsuarios(request);
                request.setAttribute("ConsultarUsuarios", html);
                RequestDispatcher view = request
                        .getRequestDispatcher("GestionarUsuario.jsp");
                view.forward(request, response);
            }
            if (page.equals("EliminarUsuario")) {
                html = EliminarUsuario(request);
                request.setAttribute("EliminarUsuario", html);
            }
            if (page.equals("ConsultarUsuario")) {
                Usuario usuario = ConsultarUsuario(request);
                request.setAttribute("ConsultarUsuario", usuario);
                RequestDispatcher view = request
                        .getRequestDispatcher("CreacionUsuario.jsp");
                view.forward(request, response);
            }
            if (page.equals("ActualizarUsuario")) {
                response.setContentType("text/html;ISO-8859-1");
                html = ActualizarUsuario(request);
            }
        } catch (ServletException | ClassNotFoundException | SQLException | IOException ex) {
            html = "<html><head><script>alert(\"Se presento un error, " + ex.getMessage().replace("\n", "").replace("\t", "").replace(" ", " ").replace(" ", " ").replace("'", "").replace("\"", "") + "\");history.back();</script></head><body></body></html>";
            if (out != null) {
                out.println(html);
                out.close();
            }
        } finally {
            if (out != null) {
                out.println(html);
                out.close();
            }
        }
    }

    /**
     * Autentica al usuario en el sistema
     *
     * @param request
     * @return String
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    private String UsuarioLogin(HttpServletRequest request) throws ClassNotFoundException, SQLException {
        String msg;
        Usuario usuario = new Usuario();
        String login = request.getParameter("txtLogin");
        String pws = request.getParameter("txtPws");
        usuario = dataAcces.ConsultarUsuarioPorLogin(login);
        if (usuario.getLogin() == null) {
            msg = "Usuario o contraseña incorrectos";
        } else {
            if (usuario.getLogin().equals("")) {
                msg = "Usuario o contraseña incorrectos";
            } else {
                if (!usuario.getPassword().equals(EncriptarPassword(pws))) {
                    msg = "Usuario o contraseña incorrectos";
                } else {
                    List<MenuComposite> menu = ConsultarMenuPorUsuario(usuario
                            .getId());
                    HttpSession session = request.getSession(true);
                    session.setAttribute("Usuario", usuario);
                    session.setAttribute("Menu", menu);
                    msg = "Bienvenido " + usuario.getNombres() + " " + usuario.getApellidos();
                }
            }
        }
        return "<html><head><script>alert('" + msg.replace("\n", "").replace("'", "") + "');window.location='Index.html';</script></head><body></body></html>";
    }

    /**
     * Cierra la sesion al usuario en el sistema
     *
     * @param request
     * @return String
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    private String UsuarioLogOut(HttpServletRequest request) throws ClassNotFoundException, SQLException {
        HttpSession session = request.getSession(true);
        Usuario usuario = (Usuario) session.getAttribute("Usuario");
        IDAL data = MySQLDAL.getInstance();
        data.closeConnect();
        if (usuario == null) {
            return "<html><head><script>alert('Por favor, inicie primero la sesión');window.location='Login.html';</script></head><body></body></html>";
        } else {
            session.invalidate();
            return "<html><head><script>alert('Gracias, " + usuario.getNombres() + " por su visita!!');window.location='Index.html';</script></head><body></body></html>";
        }
    }

    /**
     * Muestra el menu del usuario autenticado
     *
     * @param request
     * @return String
     */
    @SuppressWarnings("unchecked")
    private String CargarMenu(HttpServletRequest request) {
        String xml;
        HttpSession session = request.getSession(true);
        List<MenuComposite> menu = (List<MenuComposite>) session
                .getAttribute("Menu");
        if (menu != null) {
            if (!menu.isEmpty()) {
                xml = CrearMenu(menu);
            } else {
                xml = CrearMenuPrincipal();
            }
        } else {
            xml = CrearMenuPrincipal();
        }
        return xml;
    }

    /**
     * Registra un nuevo usuario en el sistema
     *
     * @param request
     * @return String
     */
    private String CrearUsuario(HttpServletRequest request) throws ClassNotFoundException, SQLException {
        String msg;
        Usuario usuario = new Usuario();
        usuario.setActivo(request.getParameter("rbtActive").equals("Si"));
        usuario.setIdentificacion(request.getParameter("txtIdentification"));
        usuario.setNombres(request.getParameter("txtFName"));
        usuario.setApellidos(request.getParameter("txtLName"));
        usuario.setLogin(request.getParameter("txtLogin"));
        usuario.setPassword(EncriptarPassword(request.getParameter("txtPws")));
        usuario.setIdRol(Integer.parseInt(request.getParameter("ddlRol")));
        if (dataAcces.CrearUsuario(usuario)) {
            msg = "Se registro el usuario";
        } else {
            msg = "No se registro el usuario, intente de nuevo";
        }
        return "<html><head><script>alert('" + msg.replace("\n", "").replace("'", "") + "');window.location='Index.html';</script></head><body></body></html>";
    }

    /**
     * Muestra la tabla de edicion de usuarios
     *
     * @param request
     * @return String
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    private String ConsultarUsuarios(HttpServletRequest request) throws ClassNotFoundException, SQLException {
        String noOptions = "";
        HttpSession session = request.getSession(true);
        Usuario usuarioOption = (Usuario) session.getAttribute("Usuario");
        if (usuarioOption != null) {
            if (usuarioOption.getIdRol() != 1) {
                noOptions = "display:none";
            }
        }
        String html = "";
        List<Usuario> usuarios;
        usuarios = dataAcces.ConsultarUsuarios();
        for (int i = 0; i < usuarios.size(); i++) {
            html += "<tr><td>" + usuarios.get(i).getLogin() + "</td><td>" + usuarios.get(i).getNombres() + " " + usuarios.get(i).getApellidos() + "</td><td>" + usuarios.get(i).getIdentificacion() + "</td><td>" + (usuarios.get(i).getIdRol() == 1 ? "Administrador" : usuarios.get(i).getIdRol() == 2 ? "Profesor" : usuarios.get(i).getIdRol() == 3 ? "Estudiante" : "Secretaria") + "</td><td style=\"text-align:center;" + noOptions + "\"><a href=\"SeguridadFacade?page=ConsultarUsuario&id=" + usuarios.get(i).getId() + "\"><img title=\"Editar\" src=\"Images/page_setup.gif\"/></a>&nbsp;&nbsp;<a href=\"SeguridadFacade?page=EliminarUsuario&id=" + usuarios.get(i).getId() + "\"><img title=\"Eliminar\" src=\"Images/close.gif\"/></a></td></tr>";
        }
        return html;
    }

    /**
     * Pemite eliminar logicamente un usuario
     *
     * @param request
     * @return String
     */
    private String EliminarUsuario(HttpServletRequest request) throws ClassNotFoundException, SQLException {
        String msg;
        Integer id = Integer.parseInt(request.getParameter("id"));
        Usuario usuario;
        usuario = dataAcces.ConsultarUsuarioPorId(id);
        usuario.setActivo(false);
        if (dataAcces.ActualizarUsuarioPorId(usuario)) {
            msg = "Se elimino el usuario";
        } else {
            msg = "No se elimino el usuario, intente de nuevo";
        }
        return "<html><head><script>alert('" + msg.replace("\n", "").replace("'", "") + "');window.location='SeguridadFacade?page=ConsultarUsuarios';</script></head><body></body></html>";
    }

    /**
     * Permite editar la informacion de un usuario
     *
     * @param request
     * @return String
     */
    private String ActualizarUsuario(HttpServletRequest request) throws ClassNotFoundException, SQLException {
        String msg;
        Usuario usuario = new Usuario();
        usuario.setId(Integer.parseInt(request.getParameter("id")));
        usuario.setIdentificacion(request.getParameter("txtIdentification"));
        usuario.setNombres(request.getParameter("txtFName"));
        usuario.setApellidos(request.getParameter("txtLName"));
        usuario.setLogin(request.getParameter("txtLogin"));
        usuario.setPassword(EncriptarPassword(request.getParameter("txtPws")));
        usuario.setIdRol(Integer.parseInt(request.getParameter("ddlRol")));
        usuario.setActivo(request.getParameter("rbtActive").equals("Si"));
        if (dataAcces.ActualizarUsuarioPorId(usuario)) {
            msg = "Se actualizo el usuario";
        } else {
            msg = "No se actualizo el usuario, intente de nuevo";
        }
        return "<html><head><script>alert('" + msg.replace("\n", "").replace("'", "") + "');window.location='Index.html';</script></head><body></body></html>";
    }

    /**
     * Obtiene la informacion de un usuario para edicion
     *
     * @param request
     * @return String
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    private Usuario ConsultarUsuario(HttpServletRequest request) throws ClassNotFoundException, SQLException {
        Usuario usuario;
        Integer id = Integer.parseInt(request.getParameter("id"));
        usuario = dataAcces.ConsultarUsuarioPorId(id);
        return usuario;
    }

    /**
     * Obtiene las opciones de menu para un usuario
     *
     * @param idUsuario
     * @return List<MenuComposite>
     * @throws SQLException
     * @throws ClassNotFoundException
     */
    private List<MenuComposite> ConsultarMenuPorUsuario(int idUsuario) throws SQLException, ClassNotFoundException {
        List<MenuComposite> menuAux = new Vector<>();
        List<Menu> menu;
        menu = (List<Menu>) dataAcces.ConsultarMenuPorUsuario(idUsuario);
        for (int i = 0; i < menu.size(); i++) {
            List<MenuLeaf> children = new Vector<>();
            MenuComposite parent = new MenuComposite();
            parent.setId(menu.get(i).getId());
            parent.setIdSuperMenu(menu.get(i).getIdSuperMenu());
            parent.setTitulo(menu.get(i).getTitulo());
            parent.setUrl(menu.get(i).getUrl());
            if (parent.getIdSuperMenu() == 0) {
                for (int j = 0; j < menu.size(); j++) {
                    MenuLeaf child = (MenuLeaf) menu.get(j);
                    if (child.getIdSuperMenu() == parent.getId()) {
                        children.add(child);
                    }
                }
                parent.setChildMenu(children);
                menuAux.add(parent);
            }
        }
        return menuAux;
    }

    /**
     * Obtiene la informacion de un menu estandar
     *
     * @return String
     */
    private String CrearMenuPrincipal() {
        String menu = "<?xml version=\"1.0\"?>\n" + "<menu>\n" + "<item id=\"1\" text=\"Inicio\"><href><![CDATA[Index.html]]></href></item>\n" + "<item id=\"2\" text=\"Login\"><href><![CDATA[Login.html]]></href></item>\n" + "</menu>";
        return menu;
    }

    /**
     * Crea las opciones de menu
     *
     * @param lstMenu
     * @return String
     */
    private String CrearMenu(List<MenuComposite> lstMenu) {
        String menu = "<?xml version=\"1.0\"?>\n" + "<menu>\n";
        for (int i = 0; i < lstMenu.size(); i++) {
            menu += lstMenu.get(i).CrearMenu();
        }
        menu += "</menu>";
        return menu;
    }

    /**
     * Pemite encriptar el password con el algoritmo SHA
     *
     * @param password
     * @return
     */
    public String EncriptarPassword(String password) {
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("SHA"); // step 2
        } catch (NoSuchAlgorithmException ex) {
        }
        try {
            md.update(password.getBytes("UTF-8")); // step 3
        } catch (UnsupportedEncodingException ex) {
        }
        byte raw[] = md.digest(); // step 4
        String hash = (new BASE64Encoder()).encode(raw); // step 5
        return hash; // step 6
    }
}
